package main

import (
	"chapter-05-interceptor/service"
	"context"
	"fmt"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/grpclog"
	"os"
	"path"
	"time"

	"google.golang.org/grpc"
	"log"
)

const (
	// Address gRPC服务地址
	Address = "127.0.0.1:50052"

	// OpenTLS 是否开启TLS认证
	OpenTLS = true
)

// customCredential 自定义认证
type customCredential struct{}

// GetRequestMetadata 实现自定义认证接口
func (c customCredential) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	return map[string]string{
		"appid":  "101010",
		"appkey": "i am key",
	}, nil
}

// RequireTransportSecurity 自定义认证是否开启TLS
func (c customCredential) RequireTransportSecurity() bool {
	return OpenTLS
}

func main() {

	var err error
	var opts []grpc.DialOption

	if OpenTLS {
		//获取当前目录
		dir, err := os.Getwd()
		if err != nil {
			grpclog.Fatalf("Failed to get current directory: %v", err)
		}
		creds, err := credentials.NewClientTLSFromFile(path.Join(dir, "/key/server.pem"), "ximu.info")
		if err != nil {
			grpclog.Fatalf("Failed to create TLS credentials %v", err)
		}
		// TLS连接
		if err != nil {
			grpclog.Fatalf("Failed to create TLS credentials %v", err)
		}
		opts = append(opts, grpc.WithTransportCredentials(creds))
	} else {
		opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
	}
	// 指定自定义认证
	opts = append(opts, grpc.WithPerRPCCredentials(new(customCredential)))
	// 指定客户端interceptor
	opts = append(opts, grpc.WithUnaryInterceptor(interceptor))
	conn, err := grpc.Dial(Address, opts...)
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer func(conn *grpc.ClientConn) {
		err := conn.Close()
		if err != nil {

		}
	}(conn)

	// 初始化客户端
	client := service.NewSayHelloClient(conn)

	hello := funcCallGrpc(err, client)

	if err != nil {
		log.Fatal("调用gRPC方法错误: ", err)
	}
	fmt.Println("Token：调用gRPC方法成功，ProdStock = ", hello)

}

func funcCallGrpc(err error, client service.SayHelloClient) *service.HelloResponse {
	hello, err := client.SayHello(context.Background(), &service.HelloRequest{Id: "1"})
	if err != nil {
		panic(err)
	}
	return hello
}

// interceptor 客户端拦截器
func interceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
	start := time.Now()
	err := invoker(ctx, method, req, reply, cc, opts...)
	log.Printf("method=%s req=%v rep=%v duration=%s error=%v\n\n", method, req, reply, time.Since(start), err)
	return err
}
